# -*- coding: utf-8 -*-
# @Time    : 2024/7/1 16:19
# @Author  : yujiahao
# @File    : 15_numpy_matrix_multiplication.py
# @description: NumPy矩阵乘法

"""
矩阵乘法

矩阵乘法是将两个矩阵作为输入值，并将 A 矩阵的行与 B 矩阵的列对应位置相乘再相加，从而生成一个新矩阵。

例如，给定矩阵 A 和矩阵 B：

矩阵 A:
    1  2  3
    3  4  5
    7  6  4

矩阵 B:
    5  2  6
    5  6  7
    7  6  4

矩阵乘法结果 C 为：

    36  32  32
    70  60  66
    93  74 100

具体计算过程如下：
c11 = 1*5 + 2*5 + 3*7 = 5 + 10 + 21 = 36
c12 = 1*2 + 2*6 + 3*6 = 2 + 12 + 18 = 32
c13 = 1*6 + 2*7 + 3*4 = 6 + 14 + 12 = 32

c21 = 3*5 + 4*5 + 5*7 = 15 + 20 + 35 = 70
c22 = 3*2 + 4*6 + 5*6 = 6 + 24 + 30 = 60
c23 = 3*6 + 4*7 + 5*4 = 18 + 28 + 20 = 66

c31 = 7*5 + 6*5 + 4*7 = 35 + 30 + 28 = 93
c32 = 7*2 + 6*6 + 4*6 = 14 + 36 + 24 = 74
c33 = 7*6 + 6*7 + 4*4 = 42 + 42 + 16 = 100

注意：必须确保第一个矩阵中的列数等于第二个矩阵中的行数，否则不能进行矩阵乘法运算。

矩阵乘法运算被称为向量化操作，向量化的主要目的是减少使用的 for 循环次数或者根本不使用。这样做的目的是为了加速程序的计算。
"""

import numpy as np

# 下面介绍 NumPy 提供的三种矩阵乘法，从而进一步加深对矩阵乘法的理解。

# todo 1、逐元素矩阵乘法
'''multiple() 函数用于两个矩阵的逐元素乘法
    - ndmin 参数用于指定创建数组的最小维度数。
    - 如果提供的数据维度小于 ndmin，NumPy 会在必要的位置添加新的维度以满足要求。
'''
array1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], ndmin=3)
array2 = np.array([[9, 8, 7], [6, 5, 4], [3, 2, 1]], ndmin=3)
result = np.multiply(array1, array2)

# 打印逐元素乘法的计算过程
# 计算过程:
# result[0, 0, 0] = 1 * 9 = 9
# result[0, 0, 1] = 2 * 8 = 16
# result[0, 0, 2] = 3 * 7 = 21
# result[0, 1, 0] = 4 * 6 = 24
# result[0, 1, 1] = 5 * 5 = 25
# result[0, 1, 2] = 6 * 4 = 24
# result[0, 2, 0] = 7 * 3 = 21
# result[0, 2, 1] = 8 * 2 = 16
# result[0, 2, 2] = 9 * 1 = 9

# 打印逐元素乘法结果
print("逐元素乘法结果：")
print(result)

print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

# todo 2、矩阵乘积运算
'''matmul() 用于计算两个数组的矩阵乘积。'''
array1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], ndmin=3)
array2 = np.array([[9, 8, 7], [6, 5, 4], [3, 2, 1]], ndmin=3)
result = np.matmul(array1, array2)

# 打印矩阵乘积运算的计算过程
# 计算过程:
# result[0, 0, 0] = 1*9 + 2*6 + 3*3 = 9 + 12 + 9 = 30
# result[0, 0, 1] = 1*8 + 2*5 + 3*2 = 8 + 10 + 6 = 24
# result[0, 0, 2] = 1*7 + 2*4 + 3*1 = 7 + 8 + 3 = 18
# result[0, 1, 0] = 4*9 + 5*6 + 6*3 = 36 + 30 + 18 = 84
# result[0, 1, 1] = 4*8 + 5*5 + 6*2 = 32 + 25 + 12 = 69
# result[0, 1, 2] = 4*7 + 5*4 + 6*1 = 28 + 20 + 6 = 54
# result[0, 2, 0] = 7*9 + 8*6 + 9*3 = 63 + 48 + 27 = 138
# result[0, 2, 1] = 7*8 + 8*5 + 9*2 = 56 + 40 + 18 = 114
# result[0, 2, 2] = 7*7 + 8*4 + 9*1 = 49 + 32 + 9 = 90

# 打印矩阵乘积运算结果
print("矩阵乘积运算结果：")
print(result)

print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

# todo 3、矩阵点积
'''dot() 用于计算两个数组的点积。'''
array1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], ndmin=3)
array2 = np.array([[9, 8, 7], [6, 5, 4], [3, 2, 1]], ndmin=3)
result = np.dot(array1, array2)

# 打印矩阵点积的计算过程
# 计算过程:
# result[0, 0, 0] = 1*9 + 2*6 + 3*3 = 9 + 12 + 9 = 30
# result[0, 0, 1] = 1*8 + 2*5 + 3*2 = 8 + 10 + 6 = 24
# result[0, 0, 2] = 1*7 + 2*4 + 3*1 = 7 + 8 + 3 = 18
# result[0, 1, 0] = 4*9 + 5*6 + 6*3 = 36 + 30 + 18 = 84
# result[0, 1, 1] = 4*8 + 5*5 + 6*2 = 32 + 25 + 12 = 69
# result[0, 1, 2] = 4*7 + 5*4 + 6*1 = 28 + 20 + 6 = 54
# result[0, 2, 0] = 7*9 + 8*6 + 9*3 = 63 + 48 + 27 = 138
# result[0, 2, 1] = 7*8 + 8*5 + 9*2 = 56 + 40 + 18 = 114
# result[0, 2, 2] = 7*7 + 8*4 + 9*1 = 49 + 32 + 9 = 90

# 打印矩阵点积结果
print("矩阵点积结果：")
print(result)
